<!DOCTYPE html>
<html lang="en">
<head>
  <meta charset="UTF-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>函数-元属性</title>
</head>
<body>
  
</body>

<script>
  /* 
    元属性
      一个ES6的新概念：元属性。
      正如这个名称所暗示的，元属性意在以一种属性访问的形式提供特殊的元信息，而这在以前是不可能的。
      在new.target的情况下，关键字new作为一个属性访问的上下文环境。
      显然new本身不是一个对象，这使得这种能力很特殊。
      然而，当new.target被用于一个构造器调用（一个使用new调用的函数/方法）内部时，new变成了一个虚拟上下文环境，如此new.target就可以指代这个new调用的目标构造器。

      这是一个元编程操作的典型例子，因为它的意图是从一个构造器调用内部判定原来的new的目标是什么，这一般是为了自省（检查类型/结构）或者静态属性访问。
      举例来说，你可能想根据一个构造器是被直接调用，还是通过一个子类进行调用，来使它有不同的行为：
  */

  class Parent {
    constructor() {
      if (new.target === Parent) {
        console.log( "Parent instantiated" );
      }
      else {
        console.log( "A child instantiated" );
      }
    }
  }

  class Child extends Parent {}

  var a = new Parent();
  // Parent instantiated

  var b = new Child();
  // A child instantiated

  // 这里有一个微妙的地方，在Parent类定义内部的constructor()实际上被给予了这个类的词法名称（Parent），即便语法暗示着这个类是一个与构造器分离的不同实体。
  // 警告： 与所有的元编程技术一样，要小心不要创建太过聪明的代码，而使未来的你或其他维护你代码的人很难理解。小心使用这些技巧。
</script>
</html>